﻿using IServices;
using System;
using Core.Startup;
using System.Linq.Expressions;
using Core.Helper;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.ComponentModel;

namespace Services
{
    /// <summary>
    /// 基础service
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class BaseServies<T> : CoreServices<T>, IBaseServices<T>
    {
        public BaseServies()
        {
           
        }

        /// <summary>
        /// 重写Insert方法 目的是让添加的时候可以加上自己的用户Id 以及创建时间
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public override int Add(T model)
        {
            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "CreateId", Guid.NewGuid());
            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "CreateDate", DateTime.Now);
            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "UpdateId", null);
            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "UpdateDate",null);
            return base.Add(model);
        }

        /// <summary>
        /// 重写Update方法 目的是让添加的时候可以加上自己的用户Id 以及更新时间
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public override int Update(T model)
        {
            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "UpdateId", Guid.NewGuid());
            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "UpdateDate", DateTime.Now);
            return base.Update(model);
        }

        /// <summary>
        /// 重写Update方法 目的是让添加的时候可以加上自己的用户Id 以及更新时间
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public override int  Update(Expression<Func<T, T>> selector)
        {

            //待修复


            //selector= ExpressionBuilder.And(selector, CreateEqualityExpressionForUpdateId(Guid.NewGuid()));
            //selector = ExpressionBuilder.And(selector, CreateEqualityExpressionForUpdateDate(DateTime.Now));

          

            //var nodeType = selector.Body.NodeType;

            //if (nodeType == ExpressionType.MemberAccess)
            //{
            //    var columnName = ((MemberExpression)selector.Body).Member.GetColumnAttributeName();
             
            //}
            //else if (nodeType == ExpressionType.MemberInit)
            //{
            //    var memberInitExpression = (MemberInitExpression)selector.Body;
              
            //}
            //else if (nodeType == ExpressionType.New)
            //{
            //    var newExpression = ((NewExpression)selector.Body);
            //    newExpression.Update()
            //}


            //1.
            //var memberInitExpression = ((MemberInitExpression)selector.Body);

            //ParameterExpression left = Expression.Parameter(typeof(T), "");
            //MemberInfo speciesMember = typeof(T).GetMember("UpdateId")[0];
            //MemberExpression mem = Expression.Property(left, Guid.NewGuid().ToString());

            //MemberBinding memberBinding = Expression.Bind(speciesMember, mem);

            //memberInitExpression.Bindings.ToList().Add(memberBinding);



            //2.
            //foreach (var item in memberInitExpression.Bindings)
            //{
            //    var memberAssignment = (MemberAssignment)item;

            //    var paramName = memberAssignment.Member.Name;
            //    if (paramName == "Id")
            //    {
            //        switch (memberAssignment.Expression.NodeType)
            //        {
            //            case ExpressionType.Constant:
            //                //var constantExpression = (ConstantExpression)memberAssignment.Expression;
            //                //IdObject = Guid.Parse(constantExpression.Value.ToString());
            //                break;
            //            case ExpressionType.MemberAccess:
            //                //var constantValue = ((MemberExpression)memberAssignment.Expression).MemberToValue();
            //                //IdObject = Guid.Parse(constantValue.ToString());
            //                break; ;
            //        }
            //        break;
            //    }
            //}

            //memberInitExpression.Bindings

            return base.Update(selector);
        }




        #region 拓展
        /// <summary>
        /// 动态创建Selects
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <returns></returns>

        public static Expression<Func<TSource, TResult>> CreateMemberInitExpression<TSource, TResult>()

        {

            //获取所有 DisplayName 特性的字段

            var properties = typeof(TSource).GetProperties().Where(x => x.CustomAttributes.Any(t => t.AttributeType == typeof(DisplayNameAttribute))).ToList();

            Dictionary<string, string> fieldDic = properties.ToDictionary(x => x.Name, y => y.Name);

            Expression<Func<TSource, TResult>> selector = null;

            ParameterExpression left = Expression.Parameter(typeof(TSource), "x");

            var v0 = Expression.New(typeof(TResult));

            List<MemberBinding> bindingList = new List<MemberBinding>();

            foreach (var item in fieldDic)
            {

                MemberInfo speciesMember = typeof(TSource).GetMember(item.Key)[0];

                MemberExpression mem = Expression.Property(left, item.Key);

                MemberBinding memberBinding = Expression.Bind(speciesMember, mem);

                bindingList.Add(memberBinding);

            }

            Expression body = Expression.MemberInit(v0, bindingList);

            selector = (Expression<Func<TSource, TResult>>)Expression.Lambda(body, left);

            return selector;

        }


        #endregion

        /// <summary>
        /// 重写Delete
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public override int Delete(Guid Id)
        {
            //获取Model
            var model = FirstOrDefault(CreateEqualityExpressionForId(Id));
            if (model == null) return 0;

            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "UpdateId", Guid.NewGuid());
            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "UpdateDate", DateTime.Now);
            
            return base.Delete(model);
        }

        /// <summary>
        /// 重写Delete
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public override int Delete(T model)
        {
            if (model == null) return 0;
            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "UpdateId", Guid.NewGuid());
            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "UpdateDate", DateTime.Now);
            
            return base.Delete(model);
        }


        /// <summary>
        /// 重写Remove
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public override int Remove(Guid Id)
        {
            //获取Model
            var model = FirstOrDefault(CreateEqualityExpressionForId(Id));
            if (model == null) return 0;

            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "UpdateId", Guid.NewGuid());
            CoreSolution.Tools.Extensions.ReflectExtenisons.SetValues(model, "UpdateDate", DateTime.Now);
            
            return base.Remove(model);
        }




    }
}
